`timescale 1ns / 1ps

// 1 in --> N out
module expand
#(
    parameter N     = 3,
    parameter WIDTH = 8
)
(
    input   clk,
    input   rst,
    
    input   i_vld,
    output  i_rdy,
    input   [WIDTH-1 : 0]   i_data,
    
    output  o_vld,
    input   o_rdy,
    output  [N*WIDTH-1 : 0] o_data
);

reg  [WIDTH-1 : 0]  r_data [N-1 : 0];
reg                 r_vld;
wire                r_rdy;

wire [$clog2(N)-1 : 0] idx;
wire                   idx_ena;
wire                   idx_last;

assign i_rdy = r_rdy;
assign o_vld = r_vld;

assign r_rdy = ~r_vld | o_rdy;
assign idx_ena = r_rdy & i_vld;

always @(posedge clk)
begin
    if (rst) begin
        r_vld <= 1'b0;
    end
    else begin
        if (r_rdy)
            r_vld <= i_vld & idx_last;
        if (idx_ena)
            r_data[idx] <= i_data;
    end
end

zq_counter #(
    .N  (N)
) inst_cnt
(
    .clk    (clk),
    .rst    (rst),
    .clken  (idx_ena),
    .last   (idx_last),
    .out    (idx)
);

genvar i;
generate
    for (i = 0; i < N; i = i + 1)
    begin
        assign o_data[WIDTH * i + WIDTH - 1 : WIDTH * i] = r_data[i];
    end
endgenerate

endmodule
